﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Reflection;

namespace WinnerCMS.Common
{
    /// <summary>
    /// 通用数据转换为实体类
    /// </summary>
    public class ModelHelper
    {
        /// <summary>
        /// 复制值到另外的对象上
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TU"></typeparam>
        /// <param name="from"></param>
        /// <param name="to"></param>
        public static void CopyValue<T, TU>(T from, TU to)
        {
            var myPropertyInfo = from.GetType().GetProperties();
            foreach (var pifrom in myPropertyInfo)
            {
                PropertyInfo piTo = to.GetType().GetProperty(pifrom.Name);

                if (piTo == null)
                {
                    continue;
                }
                piTo.SetValue(to, pifrom.GetValue(from, null), null);
            }
        }
        /// <summary>
        /// DataRow转换为实体类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dr"></param>
        /// <returns></returns>
        public static T ConvertToModel<T>(DataRow dr)
        {
            var l = ConvertToModel<T>(dr.Table);
            if (l.Count > 0)
            {
                return l[0];
            }
            else
            {
                return default(T);
            }
        }
        #region DataReader 第一个表转换为实体类
        /// <summary>
        /// DataReader 第一个表转换为实体类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dr"></param>
        /// <returns></returns>
        public static IList<T> ConvertToModel<T>(IDataReader dr)
        {
            IList<T> l = new List<T>();

            while (dr.Read())
            {
                T model = Activator.CreateInstance<T>();

                for (int i = 0; i < dr.FieldCount; i++)
                {
                    PropertyInfo pi = model.GetType().GetProperty(dr.GetName(i));
                    if (pi == null) continue;
                    if (pi.CanWrite == false) continue;

                    try
                    {
                        if (dr[i] != DBNull.Value)
                            pi.SetValue(model, dr[i], null);
                        else
                            pi.SetValue(model, default(T), null);
                    }
                    catch
                    {
                        pi.SetValue(model, GetDefaultValue(dr[pi.Name], pi.PropertyType), null);
                    }

                }
                l.Add(model);
            }
            dr.Close();

            return l;
        }
        #endregion

        /// <summary>
        /// DataSet 第一个表转换为实体类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ds"></param>
        /// <returns>实体类泛型集合</returns>
        public static IList<T> ConvertToModel<T>(DataSet ds)
        {
            if (ds.Tables.Count == 0)
                return new List<T>();

            return ConvertToModel<T>(ds.Tables[0]);
        }
        /// <summary>
        /// DataTable 第一个表转换为实体类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dt"></param>
        /// <returns>实体类泛型集合</returns>
        public static IList<T> ConvertToModel<T>(DataTable dt)
        {
            IList<T> l = new List<T>();

            foreach (DataRow dr in dt.Rows)
            {
                T model = Activator.CreateInstance<T>();

                foreach (DataColumn dc in dr.Table.Columns)
                {
                    PropertyInfo pi = model.GetType().GetProperty(dc.ColumnName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
                    if (pi == null) continue;
                    if (pi.CanWrite == false) continue;

                    try
                    {
                        if (dr[dc.ColumnName] != DBNull.Value)
                            pi.SetValue(model, dr[dc.ColumnName], null);
                        else
                            pi.SetValue(model, default(object), null);
                    }
                    catch
                    {
                        pi.SetValue(model, GetDefaultValue(dr[pi.Name], pi.PropertyType), null);
                    }

                }
                l.Add(model);
            }

            return l;
        }

        private static object GetDefaultValue(object obj, Type type)
        {
            if (obj == DBNull.Value)
            {
                return default(object);
            }
            else
            {
                return Convert.ChangeType(obj, type);
            }
        }

        #region 将实体类转换成DataTable

        /// <summary> 
        /// 将实体类转换成DataTable 
        /// </summary> 
        /// <typeparam name="T"></typeparam> 
        /// <param name="objlist"></param> 
        /// <returns></returns> 
        public static DataTable ConvertDataTable<T>(IList<T> objlist) where T : class
        {
            if (objlist == null || objlist.Count <= 0)
            {
                return null;
            }
            using (DataTable dt = new DataTable(typeof(T).Name))
            {
                var myPropertyInfo = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

                foreach (T t in objlist)
                {
                    if (t == null)
                    {
                        continue;
                    }

                    DataRow row = dt.NewRow();

                    for (int i = 0, j = myPropertyInfo.Length; i < j; i++)
                    {
                        PropertyInfo pi = myPropertyInfo[i];

                        string name = pi.Name;

                        if (dt.Columns[name] == null)
                        {
                            DataColumn column = new DataColumn(name, pi.PropertyType);
                            dt.Columns.Add(column);
                        }

                        row[name] = pi.GetValue(t, null);
                    }

                    dt.Rows.Add(row);
                }
                return dt;
            }
        }
        #endregion

    }
}